#include "sys.h"
#include "usart.h"
#include "Ringbuf16.h"

// static DMA_HandleTypeDef _HDMA_UART1_TX;
// static DMA_HandleTypeDef _HDMA_UART2_TX;
// static DMA_HandleTypeDef _HDMA_UART3_TX;
// static DMA_HandleTypeDef _HDMA_UART4_TX;

static Ringbuf16_ST _uRxRingBufferHandle[6];
static uint8_t* _uPointRxRingBufffer[6] = {NULL,NULL,NULL,NULL};
static uint16_t _uRingBufferSize[6] = {0,0,0,0};
static uint8_t _uRxBuffer[6] = {0};
// static uint8_t _uCompleteFlag[6] = {0};

static UART_HandleTypeDef _UART_Handler[6];
#ifndef STM32F103xB
static USART_TypeDef* _Instance[6] = {USART1,USART2,USART3,UART4};
#else
static USART_TypeDef* _Instance[6] = {USART1,USART2,USART3};
#endif
uint8_t uart_init(uint8_t u, uint32_t baudrate, uint8_t databit, uint8_t stopbit, uint8_t parity)
{
    if(u > 5)
        {return 1;}
    _UART_Handler[u].Instance = _Instance[u];
    _UART_Handler[u].Init.Mode = UART_MODE_TX_RX;
    _UART_Handler[u].Init.HwFlowCtl = UART_HWCONTROL_NONE;
    // _UART_Handler[u].Init.OverSampling = UART_OVERSAMPLING_16;
    // _UART_Handler[u].Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
    // _UART_Handler[u].Init.ClockPrescaler = UART_PRESCALER_DIV1;
    // _UART_Handler[u].AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;

    _UART_Handler[u].Init.BaudRate = baudrate;
    switch (databit)
    {
        case DATA_BITS_8:
            _UART_Handler[u].Init.WordLength = UART_WORDLENGTH_8B;
            break;
        case DATA_BITS_9:
            _UART_Handler[u].Init.WordLength = UART_WORDLENGTH_9B;
            break;
        default:
            _UART_Handler[u].Init.WordLength = UART_WORDLENGTH_8B;
            break;
    }
    switch (stopbit)
    {
        case STOP_BITS_1:
            _UART_Handler[u].Init.StopBits   = UART_STOPBITS_1;
            break;
        case STOP_BITS_2:
            _UART_Handler[u].Init.StopBits   = UART_STOPBITS_2;
            break;
        default:
            _UART_Handler[u].Init.StopBits   = UART_STOPBITS_1;
            break;
    }
    switch (parity)
    {
        case PARITY_NONE:
            _UART_Handler[u].Init.Parity     = UART_PARITY_NONE;
            break;
        case PARITY_ODD:
            _UART_Handler[u].Init.Parity     = UART_PARITY_ODD;
            break;
        case PARITY_EVEN:
            _UART_Handler[u].Init.Parity     = UART_PARITY_EVEN;
            break;
        default:
            _UART_Handler[u].Init.Parity     = UART_PARITY_NONE;
            break;
    }
    if (HAL_UART_Init(&_UART_Handler[u]) != HAL_OK)
    {
        Error_Handler();
    }
    HAL_UART_Receive_IT(&_UART_Handler[u], &_uRxBuffer[u], 1);
    Ringbuf16_Init(&_uRxRingBufferHandle[u], _uPointRxRingBufffer[u], _uRingBufferSize[u]);
    // _uCompleteFlag[u] = 1;
    return 0;
}

void uart_send(uint8_t u, uint8_t *data, uint16_t len)
{
    if(u > 5)
        {return;}
    HAL_UART_Transmit(&_UART_Handler[u],data,len,0xffffffff);
}

// void uart_send_dma(uint8_t u, uint8_t *data, uint16_t len)
// {
//     HAL_UART_Transmit_DMA(&_UART_Handler[u], data, len);
//     _uCompleteFlag[u] = 0;
// }

void uart_rev_init(uint8_t u)
{
    if(u > 5)
        {return;}
    Ringbuf16_Reset(&_uRxRingBufferHandle[u]);
}

uint16_t uart_rev_length(uint8_t u)
{
    if(u > 5)
        {return 0;}
    return Ringbuf16_Elements(&_uRxRingBufferHandle[u]);
}

int uart_get_byte(uint8_t u)
{
    if(u > 5)
        {return -1;}
    return Ringbuf16_Get(&_uRxRingBufferHandle[u]);
}

void uart_set_ringbuf(uint8_t u, void * buffer, uint16_t size)
{
    if(u > 5)
        {return;}
    _uPointRxRingBufffer[u] = buffer;
    _uRingBufferSize[u] = size;
    memset(_uPointRxRingBufffer[u],0x00,_uRingBufferSize[u]);
}

int uart_write_ready(uint8_t u)
{
    if(u > 5)
        {return 1;}
    // return _uCompleteFlag[u];
    return 1;
}

// void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
// {
//     if(huart->Instance == USART1)
//     {
//         _uCompleteFlag[0] = 1;
//     }
//     else if(huart->Instance == USART2)
//     {
//         _uCompleteFlag[1] = 1;
//     }
//     else if(huart->Instance == USART3)
//     {
//         _uCompleteFlag[2] = 1;
//     }
//     else if(huart->Instance == UART4)
//     {
//         _uCompleteFlag[3] = 1;
//     }
// }

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart->Instance == USART1)
    {
        Ringbuf16_Put(&_uRxRingBufferHandle[0],_uRxBuffer[0]);

        int icnt = 0;
        while(HAL_UART_Receive_IT(&_UART_Handler[0],&_uRxBuffer[0],1) != HAL_OK )
        {
            icnt++;
            if( icnt > 10000 )
            {
                _UART_Handler[0].RxState = HAL_UART_STATE_READY;
                __HAL_UNLOCK(&_UART_Handler[0]);
                icnt = 0;
            }
        }
    }
    else if(huart->Instance == USART2)
    {
        Ringbuf16_Put(&_uRxRingBufferHandle[1],_uRxBuffer[1]);

        int icnt = 0;
        while(HAL_UART_Receive_IT(&_UART_Handler[1],&_uRxBuffer[1],1) != HAL_OK )
        {
            icnt++;
            if( icnt > 10000 )
            {
                _UART_Handler[1].RxState = HAL_UART_STATE_READY;
                __HAL_UNLOCK(&_UART_Handler[1]);
                icnt = 0;
            }
        }
    }
    else if(huart->Instance == USART3)
    {
        Ringbuf16_Put(&_uRxRingBufferHandle[2],_uRxBuffer[2]);

        int icnt = 0;
        while(HAL_UART_Receive_IT(&_UART_Handler[2],&_uRxBuffer[2],1) != HAL_OK )
        {
            icnt++;
            if( icnt > 10000 )
            {
                _UART_Handler[2].RxState = HAL_UART_STATE_READY;
                __HAL_UNLOCK(&_UART_Handler[2]);
                icnt = 0;
            }
        }
    }
#ifndef STM32F103xB
    else if(huart->Instance == UART4)
    {
        Ringbuf16_Put(&_uRxRingBufferHandle[3],_uRxBuffer[3]);

        int icnt = 0;
        while(HAL_UART_Receive_IT(&_UART_Handler[3],&_uRxBuffer[3],1) != HAL_OK )
        {
            icnt++;
            if( icnt > 10000 )
            {
                _UART_Handler[3].RxState = HAL_UART_STATE_READY;
                __HAL_UNLOCK(&_UART_Handler[3]);
                icnt = 0;
            }
        }
    }
#endif
}

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    if(uartHandle->Instance==USART1)
    {
        // __HAL_RCC_DMA1_CLK_ENABLE();
        __HAL_RCC_USART1_CLK_ENABLE();
        __HAL_RCC_GPIOA_CLK_ENABLE();

        GPIO_InitStruct.Pin = GPIO_PIN_9;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

        GPIO_InitStruct.Pin = GPIO_PIN_10;
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

        /* USART1 DMA Init */
        /* USART1_TX Init */
        // _HDMA_UART1_TX.Instance = DMA1_Channel4;
        // _HDMA_UART1_TX.Init.Direction = DMA_MEMORY_TO_PERIPH;
        // _HDMA_UART1_TX.Init.PeriphInc = DMA_PINC_DISABLE;
        // _HDMA_UART1_TX.Init.MemInc = DMA_MINC_ENABLE;
        // _HDMA_UART1_TX.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        // _HDMA_UART1_TX.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        // _HDMA_UART1_TX.Init.Mode = DMA_NORMAL;
        // _HDMA_UART1_TX.Init.Priority = DMA_PRIORITY_LOW;
        // if (HAL_DMA_Init(&_HDMA_UART1_TX) != HAL_OK)
        // {
        //     Error_Handler();
        // }

        // __HAL_LINKDMA(uartHandle,hdmatx,_HDMA_UART1_TX);

        /* USART1 interrupt Init */
        HAL_NVIC_SetPriority(USART1_IRQn, 3, 3);
        HAL_NVIC_EnableIRQ(USART1_IRQn);

        // HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 0, 0);
        // HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);
    }
    else if(uartHandle->Instance==USART2)
    {
        __HAL_RCC_USART2_CLK_ENABLE();
        __HAL_RCC_GPIOA_CLK_ENABLE();
        // __HAL_RCC_DMA1_CLK_ENABLE();

        GPIO_InitStruct.Pin = GPIO_PIN_2;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

        GPIO_InitStruct.Pin = GPIO_PIN_3;
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

        /* USART2 DMA Init */
        /* USART2_TX Init */
        // _HDMA_UART2_TX.Instance = DMA1_Channel7;
        // _HDMA_UART2_TX.Init.Direction = DMA_MEMORY_TO_PERIPH;
        // _HDMA_UART2_TX.Init.PeriphInc = DMA_PINC_DISABLE;
        // _HDMA_UART2_TX.Init.MemInc = DMA_MINC_ENABLE;
        // _HDMA_UART2_TX.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        // _HDMA_UART2_TX.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        // _HDMA_UART2_TX.Init.Mode = DMA_NORMAL;
        // _HDMA_UART2_TX.Init.Priority = DMA_PRIORITY_LOW;
        // if (HAL_DMA_Init(&_HDMA_UART2_TX) != HAL_OK)
        // {
        //     Error_Handler();
        // }

        // __HAL_LINKDMA(uartHandle,hdmatx,_HDMA_UART2_TX);

        /* USART2 interrupt Init */
        HAL_NVIC_SetPriority(USART2_IRQn, 3, 3);
        HAL_NVIC_EnableIRQ(USART2_IRQn);

        // HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 3, 0);
        // HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);
    }
    else if(uartHandle->Instance==USART3)
    {
        // __HAL_RCC_DMA1_CLK_ENABLE();
        __HAL_RCC_USART3_CLK_ENABLE();
        __HAL_RCC_GPIOB_CLK_ENABLE();

        GPIO_InitStruct.Pin=GPIO_PIN_10;
        GPIO_InitStruct.Mode=GPIO_MODE_AF_PP;
        GPIO_InitStruct.Speed=GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOB,&GPIO_InitStruct);

        GPIO_InitStruct.Pin=GPIO_PIN_11;
        GPIO_InitStruct.Mode=GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(GPIOB,&GPIO_InitStruct);

        /* USART3 DMA Init */
        /* USART3_TX Init */
        // _HDMA_UART3_TX.Instance = DMA1_Channel2;
        // _HDMA_UART3_TX.Init.Direction = DMA_MEMORY_TO_PERIPH;
        // _HDMA_UART3_TX.Init.PeriphInc = DMA_PINC_DISABLE;
        // _HDMA_UART3_TX.Init.MemInc = DMA_MINC_ENABLE;
        // _HDMA_UART3_TX.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        // _HDMA_UART3_TX.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        // _HDMA_UART3_TX.Init.Mode = DMA_NORMAL;
        // _HDMA_UART3_TX.Init.Priority = DMA_PRIORITY_LOW;
        // if (HAL_DMA_Init(&_HDMA_UART3_TX) != HAL_OK)
        // {
        //     Error_Handler();
        // }

        // __HAL_LINKDMA(uartHandle,hdmatx,_HDMA_UART3_TX);

        HAL_NVIC_SetPriority(USART3_IRQn, 3, 3);
        HAL_NVIC_EnableIRQ(USART3_IRQn);

        // HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0);
        // HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
    }
#ifndef STM32F103xB
    else if(uartHandle->Instance==UART4)
    {
        __HAL_RCC_UART4_CLK_ENABLE();
        __HAL_RCC_GPIOC_CLK_ENABLE();
        // __HAL_RCC_DMA2_CLK_ENABLE();

        GPIO_InitStruct.Pin = GPIO_PIN_10;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

        GPIO_InitStruct.Pin = GPIO_PIN_11;
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

        // _HDMA_UART4_TX.Instance = DMA2_Channel5;
        // _HDMA_UART4_TX.Init.Direction = DMA_MEMORY_TO_PERIPH;
        // _HDMA_UART4_TX.Init.PeriphInc = DMA_PINC_DISABLE;
        // _HDMA_UART4_TX.Init.MemInc = DMA_MINC_ENABLE;
        // _HDMA_UART4_TX.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        // _HDMA_UART4_TX.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        // _HDMA_UART4_TX.Init.Mode = DMA_NORMAL;
        // _HDMA_UART4_TX.Init.Priority = DMA_PRIORITY_LOW;
        // if (HAL_DMA_Init(&_HDMA_UART4_TX) != HAL_OK)
        // {
        //     Error_Handler();
        // }

        // __HAL_LINKDMA(uartHandle,hdmatx,_HDMA_UART4_TX);
        // HAL_NVIC_SetPriority(DMA2_Channel4_5_IRQn, 0, 0);
        // HAL_NVIC_EnableIRQ(DMA2_Channel4_5_IRQn);

        HAL_NVIC_SetPriority(UART4_IRQn, 3, 3);
        HAL_NVIC_EnableIRQ(UART4_IRQn);
    }
#endif
}

void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{

    if(uartHandle->Instance==USART1)
    {
        /* USER CODE BEGIN USART1_MspDeInit 0 */

        /* USER CODE END USART1_MspDeInit 0 */
        /* Peripheral clock disable */
        __HAL_RCC_USART1_CLK_DISABLE();

        /**USART1 GPIO Configuration
        PA9     ------> USART1_TX
        PA10     ------> USART1_RX
        */
        HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);

        /* USART1 DMA DeInit */
        // HAL_DMA_DeInit(uartHandle->hdmatx);

        /* USART1 interrupt Deinit */
        HAL_NVIC_DisableIRQ(USART1_IRQn);
        /* USER CODE BEGIN USART1_MspDeInit 1 */

        /* USER CODE END USART1_MspDeInit 1 */
    }
    else if(uartHandle->Instance==USART2)
    {
        /* USER CODE BEGIN USART2_MspDeInit 0 */

        /* USER CODE END USART2_MspDeInit 0 */
        /* Peripheral clock disable */
        __HAL_RCC_USART2_CLK_DISABLE();

        /**USART2 GPIO Configuration
        PA2     ------> USART2_TX
        PA3     ------> USART2_RX
        */
        HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3);

        /* USART2 DMA DeInit */
        // HAL_DMA_DeInit(uartHandle->hdmatx);

        /* USART2 interrupt Deinit */
        HAL_NVIC_DisableIRQ(USART2_IRQn);
        /* USER CODE BEGIN USART2_MspDeInit 1 */

        /* USER CODE END USART2_MspDeInit 1 */
    }
    else if(uartHandle->Instance==USART3)
    {
        /* USER CODE BEGIN USART3_MspDeInit 0 */

        /* USER CODE END USART3_MspDeInit 0 */
        /* Peripheral clock disable */
        __HAL_RCC_USART3_CLK_DISABLE();

        /**USART3 GPIO Configuration
        PB10     ------> USART3_TX
        PB11     ------> USART3_RX
        */
        HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10|GPIO_PIN_11);

        /* USART3 DMA DeInit */
        // HAL_DMA_DeInit(uartHandle->hdmatx);

        /* USART3 interrupt Deinit */
        HAL_NVIC_DisableIRQ(USART3_IRQn);
        /* USER CODE BEGIN USART3_MspDeInit 1 */

        /* USER CODE END USART3_MspDeInit 1 */
    }
#ifndef STM32F103xB
    else if(uartHandle->Instance==UART4)
    {
        /* USER CODE BEGIN UART4_MspDeInit 0 */

        /* USER CODE END UART4_MspDeInit 0 */
        /* Peripheral clock disable */
        __HAL_RCC_UART4_CLK_DISABLE();

        /**UART4 GPIO Configuration
        PC10     ------> UART4_TX
        PC11     ------> UART4_RX
        */
        HAL_GPIO_DeInit(GPIOC, GPIO_PIN_10|GPIO_PIN_11);

        /* UART4 DMA DeInit */
        // HAL_DMA_DeInit(uartHandle->hdmatx);

        /* UART4 interrupt Deinit */
        HAL_NVIC_DisableIRQ(UART4_IRQn);
        /* USER CODE BEGIN UART4_MspDeInit 1 */

        /* USER CODE END UART4_MspDeInit 1 */
    }
#endif
}

void USART1_IRQHandler(void)
{
    HAL_UART_IRQHandler(&_UART_Handler[0]);
}

void USART2_IRQHandler(void)
{
    HAL_UART_IRQHandler(&_UART_Handler[1]);
}

void USART3_IRQHandler(void)
{
    HAL_UART_IRQHandler(&_UART_Handler[2]);
}
#ifndef STM32F103xB
void UART4_IRQHandler(void)
{
    HAL_UART_IRQHandler(&_UART_Handler[3]);
}
#endif
// void DMA1_Channel4_IRQHandler(void)
// {
//     HAL_DMA_IRQHandler(&_HDMA_UART1_TX);
// }

// void DMA1_Channel7_IRQHandler(void)
// {
//     HAL_DMA_IRQHandler(&_HDMA_UART2_TX);
// }

// void DMA1_Channel2_IRQHandler(void)
// {
//     HAL_DMA_IRQHandler(&_HDMA_UART3_TX);
// }

// void DMA2_Channel4_5_IRQHandler(void)
// {
//     HAL_DMA_IRQHandler(&_HDMA_UART4_TX);
// }

/* USER CODE BEGIN 1 */
